﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

namespace BaiDuSitemap.Edit
{
    public partial class ucSitemap : UserControl
    {
        #region Atrributes

        private Regex regex = new Regex(@"http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.IgnoreCase);

        private Thread myThread = null;
        private delegate void myDeleGateInitComboBox(int index);
        private delegate string myDeleGategetComboBoxValue();
        private delegate void myDeleGateDataGridViewLoad();
        private delegate DataGridView myDeleGategetDataGridView();
        private delegate void myDeleGateSetSitemap(bool b);
        private delegate void myDeleGateSetProgress(bool b, int index, int count);

        private bool fullGid = false;

        #endregion

        #region ucSitemap

        public ucSitemap()
        {
            InitializeComponent();
            this.pSitemap.BackColor = Color.FromArgb(5, 0, 0, 0);
            this.pProgress.BackColor = Color.FromArgb(5, 0, 0, 0);
        }

        private void ucSitemap_Load(object sender, EventArgs e)
        {
            InitComboBox(0);
        }

        private void ucSitemap_SizeChanged(object sender, EventArgs e)
        {
            this.picClose.Location = new Point(this.Width - this.picClose.Width - 3, 3);
            this.pSitemap.Location = new Point((this.Width - this.pSitemap.Width) / 2, (this.Height - this.pSitemap.Height) / 2);
            this.pProgress.Location = new Point((this.Width - this.pProgress.Width) / 2, (this.Height - this.pProgress.Height) / 2);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            this.statusStrip1.BackColor = Sitemap.AeroColor;
        }

        #endregion

        #region Event

        #region Button

        private void btnCreate_Click(object sender, EventArgs e)
        {
            if (!getStatus())
            {
                MessageBox.Show("正在进行其他操作，请等待操作完成");
                return;
            }

            if (!CheckData()) return;

            SaveFileDialog sfDialog = new SaveFileDialog();
            string filePath = null;
            try
            {
                sfDialog.ValidateNames = true;
                sfDialog.Filter = "XML文件(*.xml)|*.xml";
                sfDialog.FilterIndex = 1;
                sfDialog.DefaultExt = "xml";
                sfDialog.FileName = "Sitemap.xml";
                sfDialog.AddExtension = true;
                if (sfDialog.ShowDialog() == DialogResult.Cancel)
                {
                    return;
                }

                filePath = sfDialog.FileName;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                sfDialog.Dispose();
            }

            if (CreateSitemap(filePath))
            {
                MessageBox.Show("导出完成");
                FileInfo myfile = new FileInfo(filePath);
                if (MessageBox.Show("打开地图文件所在文件夹", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) System.Diagnostics.Process.Start(myfile.Directory.ToString());
            }
            else MessageBox.Show("操作失败");
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            if (!getStatus())
            {
                MessageBox.Show("正在进行其他操作，请等待操作完成");
                return;
            }

            InitComboBox(this.cbbGroup.SelectedIndex);
        }

        private void btnQuickModify_Click(object sender, EventArgs e)
        {
            if (!getStatus())
            {
                MessageBox.Show("正在进行其他操作，请等待操作完成");
                return;
            }

            if (this.dgvURL.Rows.Count == 0)
            {
                MessageBox.Show("选择的分组未找到网址信息");
                return;
            }

            fullGid = true;
            SetSitemap(true);
            InitComboBox();

            #region InitPanelSitemap

            string DefaultLastMod = DateTime.Now.ToString("yyyy-MM-dd");
            string DefaultFrequency = "monthly";
            decimal DefaultPriority = 0.6M;

            string LastMod = "";
            string Frequency = "";
            decimal Priority = 0.0M;
            bool LastModEn = false;

            List<string> urls = new List<string>();
            foreach (DataGridViewRow row in this.dgvURL.Rows)
            {
                urls.Add(row.Cells[0].Value.ToString());
                if (row.Cells[2].Value != null)
                {
                    if (LastMod == "")
                    {
                        LastMod = row.Cells[2].Value.ToString();
                        LastModEn = true;
                    }
                    else if (LastMod != row.Cells[2].Value.ToString())
                    {
                        LastMod = DefaultLastMod;
                        LastModEn = false;
                    }
                }

                if (row.Cells[3].Value != null)
                {
                    if (Frequency == "") Frequency = row.Cells[3].Value.ToString();
                    else if (Frequency != row.Cells[3].Value.ToString()) Frequency = DefaultFrequency;
                }

                if (row.Cells[4].Value != null)
                {
                    if (Priority == -1) Priority = decimal.Parse(row.Cells[4].Value.ToString());
                    else if (Priority != decimal.Parse(row.Cells[4].Value.ToString())) Priority = DefaultPriority;
                }
            }

            this.tbURL.Text = string.Join(";", urls.ToArray());
            this.tbURL.ReadOnly = true;


            this.cbLastModify.Checked = LastModEn;
            this.dtpLastModify.Value = DateTime.Parse(LastMod == "" ? DefaultLastMod : LastMod);

            this.cbbFrequency.SelectedValue = DBO.Code.getID(Frequency == "" ? DefaultFrequency : Frequency);

            this.nudPriority.Value = Priority == 0.0M ? DefaultPriority : Priority;

            #endregion
        }

        private void btnModify_Click(object sender, EventArgs e)
        {
            if (!getStatus())
            {
                MessageBox.Show("正在进行其他操作，请等待操作完成");
                return;
            }

            if (this.dgvURL.SelectedRows.Count == 0)
            {
                MessageBox.Show("请选择需要修改的项");
                return;
            }

            fullGid = false;
            SetSitemap(true);
            InitComboBox();

            #region InitPanelSitemap

            string DefaultLastMod = DateTime.Now.ToString("yyyy-MM-dd");
            string DefaultFrequency = "monthly";
            decimal DefaultPriority = 0.6M;

            string LastMod = "";
            string Frequency = "";
            decimal Priority = 0.0M;
            bool LastModEn = false;

            List<string> urls = new List<string>();
            foreach (DataGridViewRow row in this.dgvURL.SelectedRows)
            {
                urls.Add(row.Cells[0].Value.ToString());
                if (row.Cells[2].Value != null)
                {
                    if (LastMod == "")
                    {
                        LastMod = row.Cells[2].Value.ToString();
                        LastModEn = true;
                    }
                    else if (LastMod != row.Cells[2].Value.ToString())
                    {
                        LastMod = DefaultLastMod;
                        LastModEn = false;
                    }
                }

                if (row.Cells[3].Value != null)
                {
                    if (Frequency == "") Frequency = row.Cells[3].Value.ToString();
                    else if (Frequency != row.Cells[3].Value.ToString()) Frequency = DefaultFrequency;
                }

                if (row.Cells[4].Value != null)
                {
                    if (Priority == -1) Priority = decimal.Parse(row.Cells[4].Value.ToString());
                    else if (Priority != decimal.Parse(row.Cells[4].Value.ToString())) Priority = DefaultPriority;
                }
            }

            this.tbURL.Text = string.Join(";", urls.ToArray());
            this.tbURL.ReadOnly = true;


            this.cbLastModify.Checked = LastModEn;
            this.dtpLastModify.Value = DateTime.Parse(LastMod == "" ? DefaultLastMod : LastMod);

            this.cbbFrequency.SelectedValue = DBO.Code.getID(Frequency == "" ? DefaultFrequency : Frequency);

            this.nudPriority.Value = Priority == 0.0M ? DefaultPriority : Priority;

            #endregion
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (fullGid) myThread = new Thread(new ThreadStart(ThreadQuickModify));
            else myThread = new Thread(new ThreadStart(ThreadModify));
            myThread.Start();
            SetSitemap(false);
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            SetSitemap(false);
        }

        #endregion

        #region ComboBox

        private void cbbGroup_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cbbGroup.SelectedIndex == 0) return;

            myThread = new Thread(new ThreadStart(ThreadLoadURL));
            myThread.Start();
        }

        #endregion

        #region Picture

        private void picClose_Click(object sender, EventArgs e)
        {
            if (myThread != null && myThread.IsAlive)
            {
                if (MessageBox.Show("正在生成站点地图，确认要关闭吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }

                myThread.Abort();
            }

            this.Dispose();
        }

        private void picClose_MouseEnter(object sender, EventArgs e)
        {
            this.picClose.Image = Properties.Resources.close02;
        }

        private void picClose_MouseLeave(object sender, EventArgs e)
        {
            this.picClose.Image = Properties.Resources.close01;
        }

        #endregion

        #region DataGridView

        private void dgvURL_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            this.tsslMsg.Visible = true;
            this.tsslMsg.Text = string.Format("网址总数：{0}", this.dgvURL.RowCount);
        }

        #endregion

        #region CheckBox

        private void cbLastModify_CheckedChanged(object sender, EventArgs e)
        {
            this.dtpLastModify.Enabled = this.cbLastModify.Checked;
        }

        #endregion

        #endregion

        #region Thread

        private void ThreadLoadURL()
        {
            try
            {
                DataGridViewLoad();
            }
            catch (ThreadAbortException)
            {
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ThreadQuickModify()
        {
            DataGridView dgv = getDataGridView();

            SetProgress(true, 0, 0);
            if (DBO.URL.Update4Sitemap(int.Parse(getComboBoxValue()), this.cbLastModify.Checked ? this.dtpLastModify.Value.ToString("yyyy-MM-dd") : "", this.cbbFrequency.SelectedValue.ToString(), this.nudPriority.Value.ToString()) < 0)
            {
                MessageBox.Show("操作失败");
            }
            else
            {
                DataGridViewLoad();
            }
            SetProgress(false, 0, 0);
        }

        private void ThreadModify()
        {
            int index = 0;
            DataGridView dgv = getDataGridView();
            int count = dgv.SelectedRows.Count;

            foreach (DataGridViewRow row in dgv.SelectedRows)
            {
                SetProgress(true, index, count);

                DBO.URL.Update4Sitemap(row.Cells[0].Value.ToString(), this.cbLastModify.Checked ? this.dtpLastModify.Value.ToString("yyyy-MM-dd") : "", this.cbbFrequency.SelectedValue.ToString(), this.nudPriority.Value.ToString());
                row.Cells[2].Value = this.cbLastModify.Checked ? this.dtpLastModify.Value.ToString("yyyy-MM-dd") : "";
                row.Cells[3].Value = this.cbbFrequency.GetItemText(this.cbbFrequency.SelectedItem);
                row.Cells[4].Value = this.nudPriority.Value.ToString();
                index++;
            }

            SetProgress(false, index, count);
        }

        #endregion

        #region Method

        private void InitComboBox(int index)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateInitComboBox(InitComboBox), new object[] { index });
            }
            else
            {
                DataTable dt = DBO.Group.getAll();
                DataRow dr = null;
                dr = dt.NewRow();
                dr["gid"] = "-1";
                dr["gname"] = "--请选择--";
                dt.Rows.InsertAt(dr, 0);
                dr = dt.NewRow();
                dr["gid"] = "0";
                dr["gname"] = "--全部--";
                dt.Rows.InsertAt(dr, 1);

                this.cbbGroup.ValueMember = "gid";
                this.cbbGroup.DisplayMember = "gname";
                this.cbbGroup.DataSource = dt;
                this.cbbGroup.SelectedIndex = dt.Rows.Count - 1 < index ? 0 : index;
            }
        }

        private void InitComboBox()
        {
            DataTable dt = DBO.Code.getAllFrequency();
            this.cbbFrequency.ValueMember = "id";
            this.cbbFrequency.DisplayMember = "frequency";
            this.cbbFrequency.DataSource = dt;
            this.cbbFrequency.SelectedIndex = 0;
        }

        private string getComboBoxValue()
        {
            if (this.InvokeRequired)
            {
                return this.Invoke(new myDeleGategetComboBoxValue(getComboBoxValue)) as string;
            }
            else
            {
                return this.cbbGroup.SelectedValue.ToString();
            }
        }

        private void SetSitemap(bool b)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateSetSitemap(SetSitemap), new object[] { b });
            }
            else
            {
                this.pSitemap.Visible = b;
                this.cbbGroup.Enabled = !b;
                this.dgvURL.Enabled = !b;
            }
        }

        private void DataGridViewLoad()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateDataGridViewLoad(DataGridViewLoad));
            }
            else
            {
                DataTable dt = DBO.URL.get4Sitemap(int.Parse(getComboBoxValue()));

                this.dgvURL.AutoGenerateColumns = false;
                this.dgvURL.Columns[0].DataPropertyName = "url";
                this.dgvURL.Columns[1].DataPropertyName = "gname";
                this.dgvURL.Columns[2].DataPropertyName = "lastmod";
                this.dgvURL.Columns[3].DataPropertyName = "frequency";
                this.dgvURL.Columns[4].DataPropertyName = "priority";
                this.dgvURL.DataSource = dt;
            }
        }

        private DataGridView getDataGridView()
        {
            if (this.InvokeRequired)
            {
                return this.Invoke(new myDeleGategetDataGridView(getDataGridView)) as DataGridView;
            }
            else
            {
                return this.dgvURL;
            }
        }

        private void SetProgress(bool b, int index, int count)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateSetProgress(SetProgress), new object[] { b, index, count });
            }
            else
            {
                if (count == 0)
                {
                    this.pbProgress.Style = ProgressBarStyle.Marquee;
                    this.lblMsg.Text = "正在修改地图信息";
                }
                else
                {
                    this.pbProgress.Style = ProgressBarStyle.Blocks;
                    this.pbProgress.Maximum = count;
                    this.pbProgress.Value = index;
                    this.lblMsg.Text = string.Format("正在处理：{0}/{1}", index, count);
                }
                this.pProgress.Visible = b;
                this.cbbGroup.Enabled = !b;
                this.dgvURL.Enabled = !b;
            }
        }

        private bool CheckData()
        {
            if (this.dgvURL.RowCount == 0)
            {
                MessageBox.Show("找不到需要导出的数据");
                return false;
            }

            if (this.dgvURL.RowCount > 50000)
            {
                MessageBox.Show("百度地图最多支持5万个网址，请进行删减");
                return false;
            }

            foreach (DataGridViewRow row in this.dgvURL.Rows)
            {
                if (!regex.IsMatch(row.Cells[0].Value.ToString()))
                {
                    MessageBox.Show("第" + (row.Index + 1) + "行  " + this.dgvURL.Columns[0].Name + "  格式不正确，请检查");
                    return false;
                }

                if (row.Cells[3].Value.ToString().Length == 0)
                {
                    MessageBox.Show("第" + (row.Index + 1) + "行  " + this.dgvURL.Columns[3].Name + "  为空，请检查");
                    return false;
                }

                if (row.Cells[4].Value.ToString().Length == 0)
                {
                    MessageBox.Show("第" + (row.Index + 1) + "行  " + this.dgvURL.Columns[4].Name + "  为空，请检查");
                    return false;
                }
            }

            return true;
        }

        private bool CreateSitemap(string filePath)
        {
            XmlDocument doc = new XmlDocument();
            string xmlns = DBO.Setting.Get("XMLns");

            try
            {
                XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
                doc.AppendChild(dec);
                //创建一个根节点（一级）
                XmlElement root = doc.CreateElement("urlset");
                if (!string.IsNullOrEmpty(xmlns)) root.SetAttribute("xmlns", xmlns);
                doc.AppendChild(root);

                foreach (DataGridViewRow row in this.dgvURL.Rows)
                {
                    XmlNode node = doc.CreateElement("url");

                    XmlElement loc = doc.CreateElement("loc");
                    loc.InnerText = row.Cells[0].Value.ToString();
                    node.AppendChild(loc);

                    if (row.Cells[2].Value.ToString().Length > 0)
                    {
                        XmlElement lastmod = doc.CreateElement("lastmod");
                        lastmod.InnerText = row.Cells[2].Value.ToString();
                        node.AppendChild(lastmod);
                    }

                    if (row.Cells[3].Value.ToString().Length > 0)
                    {
                        XmlElement changefreq = doc.CreateElement("changefreq");
                        changefreq.InnerText = row.Cells[3].Value.ToString();
                        node.AppendChild(changefreq);
                    }

                    if (row.Cells[4].Value.ToString().Length > 0)
                    {
                        XmlElement priority = doc.CreateElement("priority");
                        priority.InnerText = row.Cells[4].Value.ToString();
                        node.AppendChild(priority);
                    }

                    root.AppendChild(node);
                }

                doc.Save(filePath);

                CompressFile(filePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return false;
            }

            return true;
        }

        private static void CompressFile(string path)
        {
            FileStream sourceFile = null; 
            FileStream destinationFile = null;

            try
            {
                sourceFile = File.OpenRead(path);
                destinationFile = File.Create(path + ".gz");

                byte[] buffer = new byte[sourceFile.Length];
                sourceFile.Read(buffer, 0, buffer.Length);

                using (GZipStream output = new GZipStream(destinationFile, CompressionMode.Compress))
                {
                    output.Write(buffer, 0, buffer.Length);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                if (sourceFile != null) sourceFile.Close();
                if (destinationFile != null) destinationFile.Close();
            }
        }

        public bool Closing()
        {
            if (myThread != null && myThread.IsAlive) return false;
            return true;
        }

        private bool getStatus()
        {
            if ((myThread != null && myThread.IsAlive) || this.pSitemap.Visible || this.pProgress.Visible) return false;
            return true;
        }

        #endregion
    }
}
